import queue.BoundedQueue;
import queue.BoundedQueueSplit;
import queue.BoundedQueueSplitV2;
import queue.Queue;
import java.util.Vector;

public class Test {

    static int threadNumber = 4; //  threadNumber >= 2
    static int testTimes = 1000; // the size of the benchData
    static int benchTimes = 10;

    public static void main(String[] args) {
        // int benchData[][] = new int[threadNumber][testTimes];
        // genTestData(benchData);
        // Queue<Integer> queue;

        // double costTimeOrigin = 0.0;
        // double costTimeSplit = 0.0;
        // double costTimeSplitV2 = 0.0;

        // for (int i = 0; i < benchTimes; i++) {
        //     queue = new BoundedQueue<Integer>(2*testTimes);
        //     costTimeOrigin += runTest(queue, benchData);
        //     queue = new BoundedQueueSplit<Integer>(2*testTimes);
        //     costTimeSplit += runTest(queue, benchData);
        //     queue = new BoundedQueueSplitV2<Integer>(2*testTimes);
        //     costTimeSplitV2 += runTest(queue, benchData);
        // }

        // System.out.printf("average of costTimeSplit = " + costTimeSplit / benchTimes + "\n");  
        // System.out.printf("average of costTimeSplitV2 = " + costTimeSplitV2 /  benchTimes + "\n");  
        // System.out.printf("average of costTimeOrigin = " + costTimeOrigin /  benchTimes + "\n"); 
        
        Vector<Double> vecSplit = new Vector<Double>();
        Vector<Double> vecSplitV2 = new Vector<Double>();
        Vector<Double> vecOrigin = new Vector<Double>();


        for (int i = 16; i <= 256; i+=16) {
            int threadNumber = i;
            int benchData[][] = new int[threadNumber][testTimes];
            genTestData(benchData);
            Queue<Integer> queue;
            double costTimeOrigin = 0.0;
            double costTimeSplit = 0.0;
            double costTimeSplitV2 = 0.0;
            for (int j = 0; j < benchTimes; j++) {
                queue = new BoundedQueue<Integer>(2*testTimes);
                costTimeOrigin += runTest(queue, benchData);
                queue = new BoundedQueueSplit<Integer>(2*testTimes);
                costTimeSplit += runTest(queue, benchData);
                queue = new BoundedQueueSplitV2<Integer>(2*testTimes);
                costTimeSplitV2 += runTest(queue, benchData);
            }
            double opsTimeSplit = threadNumber * testTimes * benchTimes / costTimeSplit;
            double opsTimeSplitV2 = threadNumber * testTimes * benchTimes / costTimeSplitV2;
            double opsTimeOrigin = threadNumber * testTimes * benchTimes / costTimeOrigin;
            
            vecSplit.add(opsTimeSplit);
            vecSplitV2.add(opsTimeSplitV2);
            vecOrigin.add(opsTimeOrigin);

        }

        System.out.printf("vecOrigin: [");
        for (int i = 0; i < vecOrigin.size(); i++) {
            System.out.printf(vecOrigin.get(i) + ", ");
        }
        System.out.printf("\n");

        System.out.printf("vecSplit: [");
        for (int i = 0; i < vecSplit.size(); i++) {
            System.out.printf(vecSplit.get(i) + ", ");
        }
        System.out.printf("\n");

        System.out.printf("vecSplitV2: [");
        for (int i = 0; i < vecSplitV2.size(); i++) {
            System.out.printf(vecSplitV2.get(i) + ", ");
        }
        System.out.printf("\n");


        
    }

    public static double runTest(Queue<Integer> queue, int benchData[][]) {
        RunThread[] threads = new RunThread[threadNumber];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new RunThread(queue, benchData[i]);
        }
        
        long startTime = System.nanoTime();
        try {
            for (int i = 0; i < threads.length; i++) {
                threads[i].start();
            }

            for (int i = 0; i < threads.length; i++) {
                threads[i].join();
            }
        } catch (Exception e) {
            System.out.println("Exception" + e.getMessage());
        }
        long endTime = System.nanoTime();
        double costTime = (double)(endTime - startTime);
        costTime = costTime / 1000000.0;
        System.out.printf(costTime + ",\n");    
        return costTime;
    }

    public static void genTestData(int benchData[][]) {
        // 一半的线程在入队
        // 一半的线程在出队
        for (int i = 0; i < benchData.length; i++) {
            for (int j = 0; j < benchData[i].length; j++) {
                benchData[i][j] = (i+1) % 2;
            }
        }
    }
}